#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# # author : cypro666
# # date   : 2015.08.01
# # Base class of others
from abc import ABCMeta, abstractmethod
from numpy import shape

from magic3.logger import Logger
from magic3.bivtable import *
from .utils import _normalize

__all__ = ['MethodBase', 'Log']


class MethodBase(metaclass=ABCMeta):

    def __init__(self, parameters={}):
        self._param = parameters.copy()
        self._train = None
        self._label = None
        self._testing = None
        self._results = None
        self._log = Logger(parameters['log_file']).INFO
        self.Log('inited')

    def Log(self, *args):
        self._log(self.name + ' ' + ' '.join(args))

    def save_parameters(self):
        for k, v in self._param.items():
            self._log('%s %s: %s' % (self.name, k, v))

        self._log(self.name + (' dim of train file: %d * %d' % shape(self._train)))

    def read_input(self):
        ''' read csv file and create inner data structure '''
        csv = CSV()

        csv.read(self._param['train_file'], withhead=False, strip=True, convert=float, encoding='utf-8-sig')

        self._train = csv.to_matrix(True)

        if 'label_file' in self._param:
            csv.read(self._param['label_file'], withhead=False, strip=True, convert=float, encoding='utf-8-sig')
            self._label = csv.to_array(True)
            self._label = self._label.T[0]

        if 'testing_file' in self._param and self._param['testing_file']:
            if self._param['testing_file'] != self._param['train_file']:
                csv.read(self._param['testing_file'], withhead=False, strip=True, convert=float, encoding='utf-8-sig')
                self._testing = csv.to_matrix(True)

    def json_name(self):
        return self._param['results_file'] + '.json'

    def output(self):
        ''' dump results to csv file '''
        fout = open(self._param['results_file'], 'w')
        dim = shape(self._results)

        if len(dim) == 1:
            try:
                for i in self._results:
                    fout.write('%s\n' % i)
            except Exception:
                os.path.remove(self._param['results_file'])
        else:
            try:
                fmt = ['%s'] * dim[1]
                fmt = ','.join(fmt).rstrip(',') + '\n'
                for row in self._results:
                    fout.write(fmt % tuple(row))
            except Exception:
                os.path.remove(self._param['results_file'])

        fout.close()
        # if __debug__:
        #    print(self._results)

    @abstractmethod
    def run(self, *args, **kwargs):
        ''' impemented by inherited classes '''
        raise NotImplementedError

    def _normalize(self, with_label=False, method='1'):
        ''' _normalize martix or array '''
        if method == '0':
            return
        elif method == '1':
            method = 'std'
        elif method == '2':
            method = 'norm'

        if with_label:
            self._label = _normalize(self._label, method=method)

        self._train = _normalize(self._train, method=method)
        self._testing = _normalize(self._testing, method=method)



